<?php
/**
 * lsys orm
 * @author     Lonely <shan.liu@msn.com>
 * @copyright  (c) 2017 Lonely <shan.liu@msn.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0
 */
namespace LSYS\ORMCache\Lists;

use LSYS\ORM;
use LSYS\Database\Exception;
use LSYS\ORM\Cache;

class Result extends \LSYS\Database\Result{
	protected $_cache_rows=array();
	protected $_fetch_num=-1;
	/**
	 * @var ORM
	 */
	protected $_orm;
	/**
	 * @var Cache
	 */
	protected $_cache;
	/**
	 * @param mixed $result
	 * @param string $sql
	 */
	public function __construct(ORM $orm,array $ids,Cache $cache=null)
	{
		$ids=array_values($ids);
		parent::__construct($ids, null);
		$this->_orm=$orm;
		$this->_cache=$cache===null?Cache::instance():$cache;
		$this->_total_rows = count($ids);
	}
	/**
	 * {@inheritDoc}
	 * @see \LSYS\Database\Result::__destruct()
	 */
	public function __destruct()
	{
		unset($this->_cache_rows);
	}
	/**
	 * {@inheritDoc}
	 * @see SeekableIterator::seek()
	 */
	public function seek($offset)
	{
		if (!$this->offsetExists($offset))
		{
			return false;
		}
		if(!$this->_fetch($offset)) return false;
		$this->_current_row = $offset;
	}
	/**
	 * {@inheritDoc}
	 * @see \LSYS\Database\Result::set_fetch_mode()
	 */
	public function set_fetch_mode ( $mode,$classname=NULL, array $ctorargs=NULL){
		throw new Exception("not support set_fetch_mode method.");
	}
	/**
	 * @param int $offset
	 * @return boolean
	 */
	private function _fetch($offset){
		if ($offset<=$this->_fetch_num) return true;
		$_offset=$offset-$this->_fetch_num;
		$this->_fetch_num=$offset;
		while ($_offset-->0){
			$id=array_shift($this->_result);
			if ($id==null) return false;
			$row=$this->_cache->pk_get_entity($this->_orm, $id);
			if ($row==null){
				$row=$this->_orm->where($this->_orm->primary_key(), "=", $id)->find();
			}
			$this->_cache_rows[]=$row;
		}
		return true;
	}
	/**
	 * {@inheritDoc}
	 * @see Iterator::current()
	 */
	public function current()
	{
		if (!$this->offsetExists($this->_current_row))  return null;
		if(!$this->_fetch($this->_current_row)) return null;
		return isset($this->_cache_rows[$this->_current_row])?$this->_cache_rows[$this->_current_row] : NULL;
	}
}